Shader "MyShader/BrightnessSaturationContrastCRT" {
    Properties {
        [HideInInspector]_MainTex("Base (RGB)", 2D) = "white" {}
        _Brightness("Brightness", Range(0.5, 3)) = 1
        _Saturation("Saturation", Range(0.1, 5)) = 1
        _Contrast("Contrast", Range(0.4, 3)) = 1
        
        // CRT effect parameters
        _HardScan("Scanline Hardness", Range(-20, -4)) = -8
        _HardPix("Pixel Hardness", Range(-6, -1)) = -3
        _WarpX("Warp X", Range(0, 0.1)) = 0.03
        _WarpY("Warp Y", Range(0, 0.1)) = 0.04
        _MaskDark("Mask Dark", Range(0, 1)) = 0.5
        _MaskLight("Mask Light", Range(1, 2)) = 1.5
        _EmulatedResX("Emulated Res X", Float) = 320
        _EmulatedResY("Emulated Res Y", Float) = 240
        _Interval("Base Interval", Float) = 3
        _ScanDevide("Scan Devide", Float) = 1
        _ScanSpeed("scan speed",Float) = 2
    }
 
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert_img
            #pragma fragment frag 
            #include "UnityCG.cginc"
 
            sampler2D _MainTex;
            half _Brightness;
            half _Saturation;
            half _Contrast;
            
            // CRT parameters
            float _HardScan;
            float _HardPix;
            float _WarpX;
            float _WarpY;
            float _MaskDark;
            float _MaskLight;
            float _EmulatedResX;
            float _EmulatedResY;
            float _Interval;
            float _ScanDevide; 
            float _ScanSpeed;
            
            // Helper functions for CRT effect
            float ToLinear1(float c) { return (c <= 0.04045) ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4); }
            float ToSrgb1(float c) { return (c < 0.0031308) ? c * 12.92 : 1.055 * pow(c, 0.41666) - 0.055; }

            float rand(float2 seed) {
                return frac(sin(dot(seed, float2(12.9898, 78.233))) * 43758.5453);
            }
            
            float3 Fetch(float2 pos, float2 off, sampler2D tex) {
                // float currentEX = _EmulatedResX + (_Time.w % 5);
                float currentEY = _EmulatedResY +(_Time.y * _ScanSpeed % _ScanDevide);

                float interval = _Interval;
                float phase = frac(_Time.y / interval); // 0~1循环
                float isTriggerFrame = step(0.95, phase); // 当phase接近1时返回1（最后一帧）
                //currentEY -= isTriggerFrame * 50; // 仅在触发帧减少
                
                pos = floor(pos * float2(_EmulatedResX, currentEY) + off) / float2(_EmulatedResX, currentEY);
                if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5) return float3(0.0, 0.0, 0.0);
                return tex2D(tex, pos.xy).rgb;
            }
            
            float2 Dist(float2 pos) { 
                pos = pos * float2(_EmulatedResX, _EmulatedResY); 
                return -((pos - floor(pos)) - float2(0.5, 0.5)); 
            }
            
            float Gaus(float pos, float scale) { return exp2(scale * pos * pos); }
            
            float3 Horz3(float2 pos, float off, sampler2D tex) {
                float3 b = Fetch(pos, float2(-1.0, off), tex);
                float3 c = Fetch(pos, float2( 0.0, off), tex);
                float3 d = Fetch(pos, float2( 1.0, off), tex);
                float dst = Dist(pos).x;
                float scale = _HardPix;
                float wb = Gaus(dst - 1.0, scale);
                float wc = Gaus(dst + 0.0, scale);
                float wd = Gaus(dst + 1.0, scale);
                return (b * wb + c * wc + d * wd) / (wb + wc + wd);
            }
            
            float3 Horz5(float2 pos, float off, sampler2D tex) {
                float3 a = Fetch(pos, float2(-2.0, off), tex);
                float3 b = Fetch(pos, float2(-1.0, off), tex);
                float3 c = Fetch(pos, float2( 0.0, off), tex);
                float3 d = Fetch(pos, float2( 1.0, off), tex);
                float3 e = Fetch(pos, float2( 2.0, off), tex);
                float dst = Dist(pos).x;
                float scale = _HardPix;
                float wa = Gaus(dst - 2.0, scale);
                float wb = Gaus(dst - 1.0, scale);
                float wc = Gaus(dst + 0.0, scale);
                float wd = Gaus(dst + 1.0, scale);
                float we = Gaus(dst + 2.0, scale);
                return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we);
            }
            
            float Scan(float2 pos, float off) {
                float dst = Dist(pos).y;
                return Gaus(dst + off, _HardScan);
            }
            
            float3 Tri(float2 pos, sampler2D tex) {
                float3 a = Horz3(pos, -1.0, tex);
                float3 b = Horz5(pos,  0.0, tex);
                float3 c = Horz3(pos,  1.0, tex);
                float wa = Scan(pos, -1.0);
                float wb = Scan(pos,  0.0);
                float wc = Scan(pos,  1.0);
                return a * wa + b * wb + c * wc;
            }
            
            float2 Warp(float2 pos) {
                pos = pos * 2.0 - 1.0;    
                pos *= float2(1.0 + (pos.y * pos.y) * _WarpX, 1.0 + (pos.x * pos.x) * _WarpY);
                return pos * 0.5 + 0.5;
            }
            
            float3 Mask(float2 pos) {
                pos.x += pos.y * 3.0;
                float3 mask = float3(_MaskDark, _MaskDark, _MaskDark);
                pos.x = frac(pos.x / 6.0);
                // if (pos.x < 0.333) mask.r = _MaskLight;
                // else if (pos.x < 0.666) mask.g = _MaskLight;
                // else mask.b = _MaskLight;
                return mask;
            }
            
            fixed4 frag(v2f_img i) : SV_Target {
              
                
                // Create a temporary texture with the processed color
                // (In a real implementation, you might want to render to an intermediate texture first)
                // For this example, we'll apply the CRT effect directly to the processed color
                
                // Apply CRT effect
                float2 pos = Warp(i.uv);
                float3 crtColor = Tri(pos, _MainTex) * Mask(i.uv);

                  // Apply brightness, saturation, contrast first
                fixed4 tex = tex2D(_MainTex, i.uv);
                fixed3 finalColor = crtColor * _Brightness;
                fixed luminance = 0.2125 * finalColor.r + 0.7154 * finalColor.g + 0.0721 * finalColor.b;
                fixed3 luminanceColor = fixed3(luminance, luminance, luminance);
                finalColor = lerp(luminanceColor, finalColor, _Saturation);
                fixed3 avgColor = fixed3(0.5, 0.5, 0.5);
                finalColor = lerp(avgColor, finalColor, _Contrast);
                
                // Blend between original and CRT effect based on some criteria
                // Here we're just using the CRT effect directly on the processed image
                // You might want to adjust this blending
                
                return fixed4(finalColor, tex.a);
            }
            ENDCG
        }
    }
    Fallback Off
}